package com.springboot.blog.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

import java.util.*;

@Configuration
public class ShiroConfig {


    /**
     * Shiro 的方言
     * @return
     */
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }

    /**
     * cookie对象
     * @return
     */
    public SimpleCookie rememberMeCookie() {
        // 设置cookie名称，对应login.html页面的<input type="checkbox" name="remember"/>
        SimpleCookie cookie = new SimpleCookie("rememberMe");
        // 设置cookie的过期时间，单位为秒，这里为一天
        cookie.setMaxAge(86400);
        return cookie;
    }

    /**
     * cookie管理对象
     * @return
     */
    public CookieRememberMeManager rememberMeManager() {
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberMeCookie());
        // rememberMe cookie加密的密钥
        cookieRememberMeManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag=="));
        return cookieRememberMeManager;
    }

    @Bean
    public EhCacheManager getEhCacheManager(){
        EhCacheManager ehCacheManager = new EhCacheManager();
        ehCacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
        return ehCacheManager;
    }

    /**
     * 配置 sessionManager 超时
     * @return
     */
    @Bean
    public DefaultWebSessionManager getDefaultWebSessionManager(){
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        //配置sessionManager
        sessionManager.setGlobalSessionTimeout(5*60*1000);
        return sessionManager;
    }

    @Bean
    public HashedCredentialsMatcher getHashedCredentialsMatcher(){
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        //matcher 就是用来指定加密规则
        //加密方式
        matcher.setHashAlgorithmName("md5");
        //hash 循环次数（加密次数）
        matcher.setHashIterations(1);
        return matcher;
    }

    /**
     * 配置自定义Realm
     * @return
     */
    @Bean
    public MyRealm getMyRealm(HashedCredentialsMatcher matcher){
        MyRealm myRealm = new MyRealm();
        myRealm.setCredentialsMatcher(matcher);
        return myRealm;
    }

    /**
     * 配置自定义Realm
     * @return
     */
    @Bean
    public MyUserRealm getMyUserRealm(HashedCredentialsMatcher matcher){
        MyUserRealm myUserRealm = new MyUserRealm();
        myUserRealm.setCredentialsMatcher(matcher);
        return myUserRealm;
    }

    /**
     * 配置SecurityManager
     * @return
     */
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(HashedCredentialsMatcher matcher){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //securityManager 要完成校验，需要多个realm
        Collection<Realm> realms = new ArrayList<>();
        realms.add(getMyRealm(matcher));
        realms.add(getMyUserRealm(matcher));
        securityManager.setRealms(realms);
        securityManager.setCacheManager(getEhCacheManager());
        securityManager.setSessionManager(getDefaultWebSessionManager());
        securityManager.setRememberMeManager(rememberMeManager());
        return securityManager;
    }

    /**
     * 配置过滤器
     * @param securityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        //过滤器 就是shiro就是权限校验的核心，进行认证和授权是需要SecurityManager的
        factoryBean.setSecurityManager(securityManager);

        //设置shiro的拦截器
        /**
         * anon 匿名用户可访问
         * authc 认证用户可访问
         * user 使用RememberMe 的用户可访问
         * perms 对应权限可访问
         * role 对应的角色可访问
         * logout 表示指定退出的url
         */
        Map<String,String > filterMap = new HashMap<>();
        filterMap.put("/css/**","anon");
        filterMap.put("/js/**","anon");
        filterMap.put("/static/**","anon");
        filterMap.put("/admin/**","anon");
        filterMap.put("/user/**","anon");
        filterMap.put("/admin/retrieve","anon");
        filterMap.put("/sigss","anon");
        filterMap.put("/layuiadmin/**","anon");
        filterMap.put("/role/**","anon");
        filterMap.put("/login/qq", "anon");//anon表示可以匿名访问
        filterMap.put("/login/jb", "anon");//anon表示可以匿名访问
        filterMap.put("/authorize/qq", "anon");//anon表示可以匿名访问
//        filterMap.put("/admin/**","user");
        // 配置退出过滤器，其中具体的退出代码Shiro已经替我们实现了
        filterMap.put("/admin/logout","logout");
        filterMap.put("/user/logout","logout");
        filterMap.put("/","anon");
        // 除上以外所有url都必须认证通过才可以访问，未通过认证自动访问LoginUrl
//        filterMap.put("/**","authc");


        factoryBean.setFilterChainDefinitionMap(filterMap);
        // 登录的url
        factoryBean.setLoginUrl("admin/login");
        factoryBean.setLoginUrl("user/login");
        // 未授权url
        factoryBean.setUnauthorizedUrl("/error_404.html");
        return factoryBean;
    }

    @Bean
    public SimpleMappingExceptionResolver resolver() {
        System.out.println("=======================12222");
        SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();
        Properties properties = new Properties();
        //后面加上你的处理页面即可
        properties.setProperty("org.apache.shiro.authz.UnauthorizedException", "/error_404.html");
        resolver.setExceptionMappings(properties);
        return resolver;
    }

}
